﻿namespace USElections.Model.JSON
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.Serialization;
    using USElections.Model;

    /// <summary>
    /// State class.
    /// </summary>
    [DebuggerDisplay("State {Name}")]
    [DataContract(Name = "state")]
    public class State
    {
        #region Fields
        private string name;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        [DataMember(Name = "name")]
        public string Name
        {
            get { return this.name; }
            set
            {
                this.name = value;
                this.FullName = States.GetStateFullnameByCode(this.Name);
            }
        }

        /// <summary>
        /// Gets the full name of the state.
        /// </summary>
        public string FullName
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets the number of Votes.
        /// </summary>
        [DataMember(Name = "votes")]
        public Collection<Votes> Votes { get; set; }
        #endregion

        #region Public methods
        /// <summary>
        /// Gets the leading candidate for the state or null if undecided (draw).
        /// </summary>
        /// <returns>Leading candidate or null when undecided.</returns>
        public Candidate GetLeadingCandidate()
        {
            int highestNumberOfVotes = this.Votes.Max(x => x.NumberOfVotes);

            var candidates = this.Votes.Where(x => x.NumberOfVotes == highestNumberOfVotes); // && running.Contains(x.CandidateId));

            if (candidates.Count() != 1)
            {
                // undecided.
                return null;
            }
            else
            {
                // winner
                return Data.Instance.Candidates.GetCandidateById(candidates.First().CandidateId);
            }
        }

        /// <summary>
        /// Gets Leading Party for this state.
        /// </summary>
        /// <returns>The leading party for the state.</returns>
        public Candidate.Parties GetLeadingParty()
        {
            Dictionary<Candidate.Parties, int> result = new Dictionary<Candidate.Parties, int>();

            foreach (var vote in this.Votes)
            {
                Candidate candidate = Data.Instance.Candidates.GetCandidateById(vote.CandidateId);

                if (candidate != null)
                {
                    if (result.ContainsKey(candidate.Party))
                    {
                        result[candidate.Party] += vote.NumberOfVotes;
                    }
                    else
                    {
                        result.Add(candidate.Party, vote.NumberOfVotes);
                    }
                }
            }

            int highestNumberOfVotes = 0;

            if (result.Count != 0)
            {
                highestNumberOfVotes = result.Max(x => x.Value);
            }

            var parties = result.Where(x => x.Value == highestNumberOfVotes);

            if (parties.Count() != 1)
            {
                return Candidate.Parties.Undecided;
            }
            else
            {
                return parties.First().Key;
            }
        }
        #endregion
    }
}
